package org.cx.comparator.map;

import org.cx.comparator.ComparatorConfiguration;
import org.cx.comparator.annotations.ComparatorProvider;
import org.cx.comparator.annotations.IComparatorProvider;
import org.cx.comparator.utils.ReflectAsmUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.reflect.Method;

/**
 * <p> 提供者处理器 </p>
 *
 */
public class ProviderProcessor extends MapProcessor{

    public ProviderProcessor(ComparatorConfiguration comparatorConfiguration) {
        super(comparatorConfiguration);
    }

    @Override
    protected boolean matches(Method method) {
        return AnnotationUtils.findAnnotation(method, ComparatorProvider.class)!=null;
    }

    @Override
    protected ComparatorMap doBuild(Method method) {
        final ComparatorProvider comparatorProvider = AnnotatedElementUtils.findMergedAnnotation(method, ComparatorProvider.class);
        final Class<? extends IComparatorProvider> providerClass = comparatorProvider.provider();
        final ApplicationContext applicationContext = comparatorConfiguration.getApplicationContext();
        final IComparatorProvider provider;
        if(applicationContext!=null){
            provider = applicationContext.getBean(providerClass);
        }else{
            provider = ReflectAsmUtils.<IComparatorProvider>getConstructorAccess(providerClass).newInstance();
        }
        final Class<?>[] parameterTypes = method.getParameterTypes();
        final ComparatorMap comparatorMap = new ComparatorMap(parameterTypes[0],parameterTypes[1]);
        comparatorMap.setComparatorFieldMappings(provider.provide(method));
        if(provider.byDefault(method)){
            buildByDefaultField(parameterTypes[0],parameterTypes[1], comparatorMap,provider.excludes(method));
        }
        return comparatorMap;
    }
}
